﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="XRM.cs" company="SMART business">
//   Copyright (c) 2014 All Rights Reserved
// </copyright>
// <summary>
//   The main model class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ComparisonTool.Models
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Xml.Linq;

    using ComparisonTool.Connection;

    using Microsoft.Crm.Sdk.Messages;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Messages;
    using Microsoft.Xrm.Sdk.Metadata;
    using Microsoft.Xrm.Sdk.Query;

    /// <summary>
    /// The main model class.
    /// </summary>
    public class Xrm : IXrm
    {
        /// <summary>
        /// The service 1.
        /// </summary>
        private IOrganizationService service1;

        /// <summary>
        /// The _service 2.
        /// </summary>
        private IOrganizationService service2;

        /// <summary>
        /// The connection detail 1.
        /// </summary>
        private ConnectionDetail connectionDetail1;

        /// <summary>
        /// The connection detail 2.
        /// </summary>
        private ConnectionDetail connectionDetail2;

        /// <summary>
        /// The system forms 1.
        /// </summary>
        private EntityCollection systemForms1;

        /// <summary>
        /// The system forms 2.
        /// </summary>
        private EntityCollection systemForms2;

        /// <summary>
        /// The entities 1.
        /// </summary>
        private List<EntityMetadata> entities1;

        /// <summary>
        /// The entities 2.
        /// </summary>
        private List<EntityMetadata> entities2;

        /// <summary>
        /// The class id.
        /// </summary>
        private readonly Dictionary<string, string> classId = new Dictionary<string, string>
        { 
            { "AccessPrivilegeControl", "{F93A31B2-99AC-4084-8EC2-D4027C31369A}" }, 
            { "AccessTeamEntityPicker", "{3F4E2A56-F102-4B4D-AB9C-F1574CA5BFDA}" }, 
            { "ActivitiesContainerControl", "{C72511AB-84E5-4FB7-A543-25B4FC01E83E}" }, 
            { "ActivitiesWallControl", "{6636847D-B74D-4994-B55A-A6FAF97ECEA2}" }, 
            { "ArticleContentControl", "{F02EF977-2564-4B9A-B2F0-DF083D8A019B}" }, 
            { "CheckBoxControl", "{B0C6723A-8503-4FD7-BB28-C8A06AC933C2}" }, 
            { "CompositionLinkControl", "{DB1284EF-9FFC-4E99-B382-0CC082FE2364}" }, 
            { "ConnectionControl", "{3246F906-1F71-45F7-B11F-D7BE0F9D04C9}" }, 
            { "ConnectionRoleObjectTypeListControl", "{821ACF1A-7E46-4A0C-965D-FE14A57D78C7}" }, 
            { "CoverPagePicklistControl", "{4168A05C-D857-46AF-8457-5BB47EB04EA1}" }, 
            { "DateTimeControl", "{5B773807-9FB2-42DB-97C3-7A91EFF8ADFF}" }, 
            { "DecimalControl", "{C3EFE0C3-0EC6-42BE-8349-CBD9079DFD8E}" }, 
            { "DurationControl", "{AA987274-CE4E-4271-A803-66164311A958}" }, 
            { "EmailAddressControl", "{ADA2203E-B4CD-49BE-9DDF-234642B43B52}" }, 
            { "EmailBodyControl", "{6F3FB987-393B-4D2D-859F-9D0F0349B6AD}" }, 
            { "ErrorStatusControl", "{F4C16ECA-CA81-4E39-9448-834B8378721E}" }, 
            { "FloatControl", "{0D2C745A-E5A8-4C8F-BA63-C6D3BB604660}" }, 
            { "FrameControl", "{FD2A7985-3187-444E-908D-6624B21F69C0}" }, 
            { "GridControl", "{E7A81278-8635-4D9E-8D4D-59480B391C5B}" }, 
            { "HiddenInputControl", "{5546E6CD-394C-4BEE-94A8-4425E17EF6C6}" }, 
            { "IntegerControl", "{C6D124CA-7EDA-4A60-AEA9-7FB8D318B68F}" }, 
            { "KBViewerControl", "{A62B6FA9-169E-406C-B1AA-EAB828CB6026}" }, 
            { "LanguagePicker", "{671A9387-CA5A-4D1E-8AB7-06E39DDCF6B5}" }, 
            { "LinkControl", "{DFDF1CDE-837B-4AC9-98CF-AC74361FD89D}" }, 
            { "LookupControl", "{270BD3DB-D9AF-4782-9025-509E298DEC0A}" }, 
            { "MailMergeLanguagePicker", "{B634828E-C390-444A-AFE6-E07315D9D970}" }, 
            { "MapLinkControl", "{91DC0675-C8B9-4421-B1E0-261CEBF02BAC}" }, 
            { "MapsControl", "{62B0DF79-0464-470F-8AF7-4483CFEA0C7D}" }, 
            { "MoneyControl", "{533B9E00-756B-4312-95A0-DC888637AC78}" }, 
            { "NotesControl", "{06375649-C143-495E-A496-C962E5B4488E}" }, 
            { "PartyListControl", "{CBFB742C-14E7-4A17-96BB-1A13F7F64AA2}" }, 
            { "PhoneNumberControl", "{8C10015A-B339-4982-9474-A95FE05631A5}" }, 
            { "PicklistControl", "{3EF39988-22BB-4F0B-BBBE-64B5A3748AEE}" }, 
            { "PicklistLookupControl", "{2305E33A-BAD3-4022-9E15-1856CF218333}" }, 
            { "PicklistStatusControl", "{5D68B988-0661-4DB2-BC3E-17598AD3BE6C}" }, 
            { "ProcessControl", "{06E9F7AF-1F54-4681-8EEC-1E21A1CEB465}" }, 
            { "QuickFormCollectionControl", "{5C5600E0-1D6E-4205-A272-BE80DA87FD42}" }, 
            { "QuickFormControl", "{69AF7DCA-2E3B-4EE7-9201-0DA731DD2413}" }, 
            { "RadioControl", "{67FAC785-CD58-4F9F-ABB3-4B7DDC6ED5ED}" }, 
            { "RegardingControl", "{F3015350-44A2-4AA0-97B5-00166532B5E9}" }, 
            { "RelatedInformationControl", "{163B90A6-EB64-49D2-9DF8-3C84A4F0A0F8}" }, 
            { "RelationshipRolePicklist", "{5F986642-5961-4D9F-AB5E-643D71E231E9}" }, 
            { "ReportControl", "{A28F441B-916C-4865-87FD-0C5D53BD59C9}" }, 
            { "TextAreaControl", "{E0DECE4B-6FC8-4A8F-A065-082708572369}" }, 
            { "TextBoxControl", "{4273EDBD-AC1D-40D3-9FB2-095C621B552D}" }, 
            { "TickerControl", "{1E1FC551-F7A8-43AF-AC34-A8DC35C7B6D4}" }, 
            { "TimeZonePicklistControl", "{7C624A0B-F59E-493D-9583-638D34759266}" }, 
            { "UrlControl", "{71716B6C-711E-476C-8AB8-5D11542BFB47}" }, 
            { "WebResourceHtmlControl", "{9FDF5F91-88B1-47F4-AD53-C11EFC01A01D}" }, 
            { "WebResourceImageControl", "{587CDF98-C1D5-4BDE-8473-14A0BC7644A7}" }, 
            { "WebResourceSilverlightControl", "{080677DB-86EC-4544-AC42-F927E74B491F}" }, 
        };

        public int BuildNumber1 { get; set; }

        public int BuildNumber2 { get; set; }

        /// <summary>
        /// Gets or sets the service 1.
        /// </summary>
        private IOrganizationService Service1
        {
            get
            {
                return this.service1;
            }

            set
            {
                if (value == null)
                {
                    this.Entities1 = null;
                }

                this.service1 = value;
            }
        }

        /// <summary>
        /// Gets or sets the service 2.
        /// </summary>
        private IOrganizationService Service2
        {
            get
            {
                return this.service2;
            }

            set
            {
                if (value == null)
                {
                    this.Entities2 = null;
                }

                this.service2 = value;
            }
        }

        /// <summary>
        /// Gets or sets the entities 1.
        /// </summary>
        private List<EntityMetadata> Entities1
        {
            get
            {
                return this.entities1;
            }

            set
            {
                if (value == null)
                {
                    // this.view.ClearEntitiesList();
                    // this.CurrentEntity = null;
                }
                else
                {
                    this.entities1 = value;
                }
            }
        }

        /// <summary>
        /// Gets or sets the entities 2.
        /// </summary>
        private List<EntityMetadata> Entities2
        {
            get
            {
                return this.entities2;
            }

            set
            {
                if (value == null)
                {
                    // this.view.ClearEntitiesList();
                    // this.CurrentEntity = null;
                }
                else
                {
                    this.entities2 = value;
                }
            }
        }

        public void RetrieveEntities(int id)
        {
            try
            {
                var service = this.GetService(id);

                var request = new RetrieveAllEntitiesRequest
                {
                    EntityFilters = EntityFilters.Entity,
                    RetrieveAsIfPublished = true
                };

                var result = (RetrieveAllEntitiesResponse)service.Execute(request);

                switch (id)
                {
                    case 1:
                        this.Entities1 = result.EntityMetadata.ToList();
                        break;
                    case 2:
                        this.Entities2 = result.EntityMetadata.ToList();
                        break;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private IOrganizationService GetService(int id)
        {
            switch (id)
            {
                case 1:
                    return this.Service1;
                case 2:
                    return this.Service2;
                default:
                    throw new Exception("Invalid organization id.");
            }
        }

        /// <summary>
        /// The retrieve system form entities request.
        /// </summary>
        /// <param name="service">
        /// The service.
        /// </param>
        /// <param name="filteredEntityName">
        /// The filtered entity name.
        /// </param>
        /// <returns>
        /// The <see cref="EntityCollection"/>.
        /// </returns>
        private EntityCollection RetrieveSystemFormEntitiesRequest(IOrganizationService service, string filteredEntityName)
        {
            var query = new QueryExpression("systemform") { ColumnSet = new ColumnSet("formxml", "name") };
            query.Criteria.AddCondition("objecttypecode", ConditionOperator.Equal, filteredEntityName);
            query.Criteria.AddCondition("type", ConditionOperator.Equal, "2");

            try
            {
                var res = service.RetrieveMultiple(query);
                return res;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex.InnerException);
            }
        }

        public List<object> RetrieveEntityForms(int orgId, string entityName)
        {
            var service = this.GetService(orgId);

            var systemForms = this.RetrieveSystemFormEntitiesRequest(service, entityName);

            this.SetSustemForms(orgId, systemForms);

            return (from SystemForm form in systemForms.Entities
                    select new { Name = form.GetAttributeValue<string>("name"), Value = form.LogicalName }).ToList<object>();
        }

        private void SetSustemForms(int id, EntityCollection systemForms)
        {
            switch (id)
            {
                case 1:
                    this.systemForms1 = systemForms;
                    break;
                case 2:
                    this.systemForms2 = systemForms;
                    break;
            }
        }

        /// <summary>
        /// The compare attributes.
        /// </summary>
        /// <param name="form1Xml">
        /// The form 1 xml.
        /// </param>
        /// <param name="form2Xml">
        /// The form 2 xml.
        /// </param>
        /// <param name="items1">
        /// The items 1.
        /// </param>
        /// <param name="items2">
        /// The items 2.
        /// </param>
        public void CompareAttributes(string form1Xml, string form2Xml, out string[] items1, out string[] items2)
        {
            items1 = GetEntityAttributes(form1Xml).Select(p => p.Value).ToArray();
            items2 = GetEntityAttributes(form2Xml).Select(p => p.Value).ToArray();
        }

        /// <summary>
        /// The compare navigation items.
        /// </summary>
        /// <param name="form1Xml">
        /// The form 1 xml.
        /// </param>
        /// <param name="form2Xml">
        /// The form 2 xml.
        /// </param>
        /// <param name="items1">
        /// The items 1.
        /// </param>
        /// <param name="items2">
        /// The items 2.
        /// </param>
        public void CompareNavigationItems(string form1Xml, string form2Xml, out string[] items1, out string[] items2)
        {
            items1 = this.GetNavigationItems(form1Xml).Select(p => p.Value).ToArray();
            items2 = this.GetNavigationItems(form2Xml).Select(p => p.Value).ToArray();
        }

        /// <summary>
        /// The compare sections.
        /// </summary>
        /// <param name="form1Xml">
        /// The form 1 xml.
        /// </param>
        /// <param name="form2Xml">
        /// The form 2 xml.
        /// </param>
        /// <param name="items1">
        /// The items 1.
        /// </param>
        /// <param name="items2">
        /// The items 2.
        /// </param>
        public void CompareSections(string form1Xml, string form2Xml, out string[] items1, out string[] items2)
        {
            items1 = GetSections(form1Xml).Select(p => p.Value).ToArray();
            items2 = GetSections(form2Xml).Select(p => p.Value).ToArray();
        }

        /// <summary>
        /// The compare tabs.
        /// </summary>
        /// <param name="form1Xml">
        /// The form 1 xml.
        /// </param>
        /// <param name="form2Xml">
        /// The form 2 xml.
        /// </param>
        /// <param name="items1">
        /// The items 1.
        /// </param>
        /// <param name="items2">
        /// The items 2.
        /// </param>
        public void CompareTabs(string form1Xml, string form2Xml, out string[] items1, out string[] items2)
        {
            items1 = this.GetTabs(form1Xml).Select(p => p.Value).ToArray();
            items2 = this.GetTabs(form2Xml).Select(p => p.Value).ToArray();
        }

        /// <summary>
        /// The compare events.
        /// </summary>
        /// <param name="form1Xml">
        /// The form 1 xml.
        /// </param>
        /// <param name="form2Xml">
        /// The form 2 xml.
        /// </param>
        /// <param name="items1">
        /// The items 1.
        /// </param>
        /// <param name="items2">
        /// The items 2.
        /// </param>
        public void CompareEvents(string form1Xml, string form2Xml, out JsEvent[] items1, out JsEvent[] items2)
        {
            items1 = this.GetFormMethods(form1Xml);
            items2 = this.GetFormMethods(form2Xml);
        }

        /// <summary>
        /// The compare rules.
        /// </summary>
        /// <param name="entityLogicalName">
        /// The entity logical name.
        /// </param>
        /// <param name="items1">
        /// The items 1.
        /// </param>
        /// <param name="items2">
        /// The items 2.
        /// </param>
        public void CompareRules(string entityLogicalName, out BusinessRule[] items1, out BusinessRule[] items2)
        {
            items1 =
                this.GetRules(this.Service1, entityLogicalName)
                    .Entities.Select(
                        p =>
                        new BusinessRule(
                            p.GetAttributeValue<EntityReference>("createdby").Name,
                            p.Id,
                            p.GetAttributeValue<EntityReference>("processid").Name,
                            p.GetAttributeValue<OptionSetValue>("componentstate").Value,
                            p.GetAttributeValue<bool>("ismanaged"))).ToArray();

            items2 =
                this.GetRules(this.service2, entityLogicalName)
                    .Entities.Select(
                        p =>
                        new BusinessRule(
                            p.GetAttributeValue<EntityReference>("createdby").Name,
                            p.Id,
                            p.GetAttributeValue<EntityReference>("processid").Name,
                            p.GetAttributeValue<OptionSetValue>("componentstate").Value,
                            p.GetAttributeValue<bool>("ismanaged"))).ToArray();
        }

        /// <summary>
        /// The get display name.
        /// </summary>
        /// <param name="formXml">
        /// The form xml.
        /// </param>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <param name="controlType">
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetDisplayName(string formXml, string name, CompareType controlType)
        {
            var form = XElement.Parse(formXml);

            var rootDescendant = "cell";
            var firstLeveldescendant = "control";
            var idNodeName = "id";

            switch (controlType)
            {
                case CompareType.Attributes:
                    break;
                case CompareType.Relationships:
                    rootDescendant = "NavBar";
                    firstLeveldescendant = "NavBarByRelationshipItem";
                    idNodeName = "Id";
                    break;
                case CompareType.Sections:
                    rootDescendant = "sections";
                    firstLeveldescendant = "section";
                    idNodeName = "name";
                    break;
                case CompareType.Tabs:
                    rootDescendant = "tab";
                    firstLeveldescendant = "labels";
                    idNodeName = "name";
                    break;
            }

            var cells = (from XElement control in form.Descendants(rootDescendant)
                         select control).ToArray();

            foreach (var item in cells)
            {
                if (item.Descendants(firstLeveldescendant).ToArray().Length != 0)
                {
                    var element = item;

                    if (controlType.Equals(CompareType.Relationships))
                    {
                        element =
                            (from XElement control in item.Descendants(firstLeveldescendant)
                             where control.Attribute(idNodeName).Value.Equals(name)
                             select control).FirstOrDefault();

                        if (element != null)
                        {
                            var title = element.Descendants("Title").FirstOrDefault();

                            if (title != null)
                            {
                                return title.Attribute("Text").Value;
                            }
                        }
                    }
                    else
                        if (controlType != CompareType.Tabs)
                        {
                            element = item.Descendants(firstLeveldescendant).FirstOrDefault();
                        }

                    if (element != null)
                    {
                        var itemId = element.Attribute(idNodeName).Value;

                        if (itemId.Equals(name))
                        {
                            var label = item.Descendants("label").FirstOrDefault();
                            if (label != null)
                            {
                                return label.Attribute("description").Value;
                            }
                        }
                    }
                }
            }

            return string.Empty;
        }

        /// <summary>
        /// The is read only.
        /// </summary>
        /// <param name="formXml">
        /// The form xml.
        /// </param>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string IsReadOnly(string formXml, string name)
        {
            var form = XElement.Parse(formXml);

            var cells = (from XElement control in form.Descendants("control")
                         select control).ToArray();

            foreach (var item in cells)
            {
                var id = item.Attribute("id").Value;

                if (item.Attribute("disabled") != null && id.Equals(name))
                {
                    var isDisabled = item.Attribute("disabled").Value;

                    if (isDisabled.Equals("false"))
                    {
                        return "No";
                    }

                    return "Yes";
                }
            }

            return "No";
        }

        /// <summary>
        /// The is hidden.
        /// </summary>
        /// <param name="formXml">
        /// The form xml.
        /// </param>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string IsHidden(string formXml, string name)
        {
            var form = XElement.Parse(formXml);

            var cells = (from XElement control in form.Descendants("cell")
                         select control).ToArray();

            foreach (var item in cells)
            {
                if (item.Descendants("control").ToArray().Length != 0)
                {
                    var control = item.Descendants("control").FirstOrDefault();
                    if (control != null)
                    {
                        var itemId = control.Attribute("id").Value;

                        if (itemId.Equals(name))
                        {
                            var isHidden = item.Attribute("visible");

                            if (isHidden == null || isHidden.Value.Equals("false"))
                            {
                                return "No";
                            }

                            return "Yes";
                        }
                    }
                }
            }

            return "No";
        }

        /// <summary>
        /// The get attribute type.
        /// </summary>
        /// <param name="formXml">
        /// The form xml.
        /// </param>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <param name="controlType">
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetAttributeType(string formXml, string name, CompareType controlType)
        {
            var form = XElement.Parse(formXml);

            var controls = (from XElement control in form.Descendants("control")
                            select control).ToArray();

            foreach (var item in controls)
            {
                var itemId = item.Attribute("id").Value;

                if (itemId.Equals(name))
                {
                    var id = item.Attribute("classid").Value.ToUpper();

                    foreach (var attributeId in this.classId)
                    {
                        if (attributeId.Value.ToUpper().Equals(id))
                        {
                            return attributeId.Key;
                        }
                    }
                }
            }

            return controlType.ToString();
        }

        /// <summary>
        /// The get attribute display name.
        /// </summary>
        /// <param name="formXml">
        /// The form xml.
        /// </param>
        /// <param name="eventType">
        /// The event type.
        /// </param>
        /// <param name="functionName">
        /// The function name.
        /// </param>
        /// <param name="libraryName">
        /// The library name.
        /// </param>
        /// <param name="eventHandlers">
        /// The event handlers.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetAttributeDisplayName(string formXml, string eventType, string functionName, string libraryName, List<JsEvent> eventHandlers)
        {
            var form = XElement.Parse(formXml);
            var events = (from jsEvent in form.Descendants("event")
                          where jsEvent.Attribute("name").Value.Equals(eventType)
                          select jsEvent).ToArray();

            foreach (var javaEvent in events)
            {
                var javaScriptHandler = from handler in javaEvent.Descendants("Handler")
                                        where handler.Attribute("functionName").Value.Equals(functionName)
                                        where handler.Attribute("libraryName").Value.Equals(libraryName)
                                        select handler;

                if (!javaScriptHandler.Count().Equals(0))
                {
                    var attribute = javaEvent.Attribute("attribute");
                    if (attribute == null)
                    {
                        return string.Empty;
                    }

                    var isAttributeChecked = (from jsEventHandler in eventHandlers
                                              where jsEventHandler.Attribute.Equals(attribute.Value)
                                              where jsEventHandler.FunctionName.Equals(functionName)
                                              where jsEventHandler.LibraryName.Equals(libraryName)
                                              select jsEventHandler).Count<JsEvent>().Equals(0);

                    if (isAttributeChecked)
                    {
                        return attribute.Value;
                    }
                }
            }

            return string.Empty;
        }

        /// <summary>
        /// The get user id.
        /// </summary>
        /// <param name="service">
        /// The service.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetUserId(IOrganizationService service)
        {
            try
            {
                var request = new WhoAmIRequest();
                var result = (WhoAmIResponse)service.Execute(request);

                return result.UserId.ToString();
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// The get org info.
        /// </summary>
        /// <param name="connectionDetail">
        /// Connection Detail
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetOrgInfo(ConnectionDetail connectionDetail)
        {
            return connectionDetail != null ? connectionDetail.OrganizationFriendlyName : string.Empty;
        }

        /// <summary>
        /// The get org info.
        /// </summary>
        /// <param name="connectionId">
        /// The connection id.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetOrgInfo(int connectionId)
        {
            switch (connectionId)
            {
                case 2:
                    return this.GetOrgInfo(this.connectionDetail2);
                default:
                    return this.GetOrgInfo(this.connectionDetail1);
            }
        }

        /// <summary>
        /// The is connected.
        /// </summary>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool IsConnected()
        {
            return this.Service1 != null && this.Service2 != null;
        }

        public string GetFormXml(int orgId, string formName, string logicalName)
        {
            var formXml = (string)(from entity in this.GetSustemForms(orgId).Entities
                                   where entity["name"].Equals(formName) && entity.LogicalName.Equals(logicalName)
                                   select entity["formxml"]).FirstOrDefault();

            if (string.IsNullOrEmpty(formXml))
            {
                throw new Exception("Form xml is empty or absent.");
            }

            return formXml;
        }

        public List<object> GetEntities(int id)
        {
            switch (id)
            {
                case 1:
                    return this.Entities1 != null ? this.Entities1.ToList<object>() : null;
                default:
                    return this.Entities2 != null ? this.Entities2.ToList<object>() : null;
            }
        }

        public int GetBuildNumber1()
        {
            return this.BuildNumber1;
        }

        public int GetBuildNumber2()
        {
            return this.BuildNumber2;
        }

        private EntityCollection GetSustemForms(int id)
        {
            switch (id)
            {
                case 1:
                    return this.systemForms1;
                case 2:
                    return this.systemForms2;
                default:
                    return null;
            }
        }

        /// <summary>
        /// The get entity value by name.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="entityName">
        ///     The entity name.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetEntityValueByName(int id, string entityName)
        {
            if (string.IsNullOrEmpty(entityName))
            {
                return string.Empty;
            }

            var entities = this.GetEntities(id);

            var value = (from dynamic entity in entities
                         where entity.LogicalName.Equals(entityName)
                         select entity.DisplayName.UserLocalizedLabel.Label).FirstOrDefault();

            return value;
        }

        /// <summary>
        /// The сonnection succeed.
        /// </summary>
        /// <param name="organizationService">
        /// The organization service.
        /// </param>
        /// <param name="connectionDetail">
        /// The connection detail.
        /// </param>
        /// <param name="id">
        /// The id.
        /// </param>
        public void СonnectionSucceed(
            IOrganizationService organizationService,
            ConnectionDetail connectionDetail,
            int id)
        {
            switch (id)
            {
                case 1:
                    this.BuildNumber1 = connectionDetail.OrganizationMajorVersion;
                    this.Service1 = organizationService;
                    this.connectionDetail1 = connectionDetail;
                    break;
                case 2:
                    this.BuildNumber2 = connectionDetail.OrganizationMajorVersion;
                    this.Service2 = organizationService;
                    this.connectionDetail2 = connectionDetail;
                    break;
            }
        }

        private static IEnumerable<XAttribute> GetSections(string formXml)
        {
            var form = XElement.Parse(formXml);

            var res = from elem in form.Descendants("sections")
                                .Descendants("section")
                      select elem.Attribute("name");

            var attributes = res as IList<XAttribute> ?? res.ToList();

            return attributes;
        }

        /// <summary>
        /// The get entity attributes.
        /// </summary>
        /// <param name="formXml">
        /// The form xml.
        /// </param>
        /// <returns>
        /// The <see cref="Enumerable"/>.
        /// </returns>
        private static IEnumerable<XAttribute> GetEntityAttributes(string formXml)
        {
            var form = XElement.Parse(formXml);

            return from elem in form.Descendants("control")
                   select elem.Attribute("id");
        }

        /// <summary>
        /// The get rules.
        /// </summary>
        /// <param name="service">
        /// The service.
        /// </param>
        /// <param name="entityLogicalName">
        /// The entity logical name.
        /// </param>
        /// <returns>
        /// The <see cref="EntityCollection"/>.
        /// </returns>
        private EntityCollection GetRules(IOrganizationService service, string entityLogicalName)
        {
            var request = new QueryExpression(ProcessTrigger.EntityLogicalName) { ColumnSet = new ColumnSet("ismanaged", "componentstate", "processid", "createdby") };
            request.Criteria.AddCondition("primaryentitytypecode", ConditionOperator.Equal, entityLogicalName);
            request.Criteria.AddCondition("event", ConditionOperator.Equal, "load");
            return service.RetrieveMultiple(request);
        }

        private JsEvent[] GetFormMethods(string formXml)
        {
            var form = XElement.Parse(formXml);

            var events = from elem in form.Descendants("events").Descendants("event")
                         select elem;

            var eventHandlers = new List<JsEvent>();

            foreach (var item in events)
            {
                var name = item.Attribute("name").Value;

                var handlers = item.Descendants("Handler");

                foreach (var handler in handlers)
                {
                    var attrName = this.GetAttributeDisplayName(formXml, name, handler.Attribute("functionName").Value, handler.Attribute("libraryName").Value, eventHandlers);
                    var attrDisplayName = string.IsNullOrEmpty(attrName) ? string.Empty : this.GetDisplayName(formXml, attrName, CompareType.Events);

                    var eventHandler = new JsEvent
                    {
                        Name = name,
                        FunctionName = handler.Attribute("functionName").Value,
                        LibraryName = handler.Attribute("libraryName").Value,
                        Attribute = attrName,
                        AttributeDisplayName = attrDisplayName
                    };

                    eventHandlers.Add(eventHandler);
                }
            }

            return eventHandlers.ToArray();
        }

        /// <summary>
        /// The get tabs.
        /// </summary>
        /// <param name="formXml">
        /// The form xml.
        /// </param>
        /// <returns>
        /// The <see cref="Enumerable"/>.
        /// </returns>
        private IEnumerable<XAttribute> GetTabs(string formXml)
        {
            var form = XElement.Parse(formXml);

            return from elem in form.Descendants("tabs")
                                .Descendants("tab")
                   select elem.Attribute("name");
        }

        /// <summary>
        /// The get navigation items.
        /// </summary>
        /// <param name="formXml">
        /// The form xml.
        /// </param>
        /// <returns>
        /// The <see cref="Enumerable"/>.
        /// </returns>
        private IEnumerable<XAttribute> GetNavigationItems(string formXml)
        {
            var form = XElement.Parse(formXml);

            return from elem in form.Descendants("Navigation")
                                    .Descendants("NavBar")
                                    .Descendants("NavBarByRelationshipItem")
                   select elem.Attribute("Id");
        }
    }
}
